Published
Edited
Feb 25, 2021
10 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof cluster_chart = {
kmeans(data, clusters);

// variables to get the dashboard to fit nicely
const scatter_sq = width * 0.47;
const hist_width = width * 0.36;
const num_hist = hist_columns.length; // hist_columns is defined in "Data Manipulation" section
// brushing and linking example from https://observablehq.com/@uwdata/interaction
const brush = vl.selectInterval().encodings('x').resolve('intersect');
// base histogram
const hist = vl.markBar()
.encode(
vl.x().fieldQ(vl.repeat('row'))
.bin({maxbins: 100, minstep: 1}) // up to 100 bins, but no smaller than 1 unit
.axis({format: 'd', titleAnchor: 'start'}), // integer format, left-aligned title
vl.y().count().title(null));

// combined histogram with total in grey and selected in blue (when selected)
// and repeated for each of the attributes
const hist_layer = vl.layer(
hist.select(brush).encode(vl.color().value('lightgrey')), // turn all grey when selected
hist.transform(vl.filter(brush))) // layer selected values on top in default blue
.height((scatter_sq/num_hist)-(10*num_hist))
.width(hist_width)
.repeat({row: hist_columns});
// scatterplot
const scatter = vl.markPoint()
.height(scatter_sq).width(scatter_sq)
.encode(
vl.x().fieldQ("x").title(x),
vl.y().fieldQ("y").title(y),
vl.color().if(brush, vl.fieldN('cluster')).value('grey'),
vl.opacity().if(brush, vl.value(0.8)).value(0.1),
vl.tooltip(quant_columns.concat(['Name', 'cluster']))
);
// place the histograms and scatterplot
return vl.hconcat(hist_layer, scatter)
.data(data)
.render();
}
Insert cell
Insert cell
Insert cell
countries = uniqueValid(cars, d=>d.Origin)
Insert cell
chart = {
// menu to select country
const selection = vl.selectSingle('Select')
.fields('Origin')
.bind({Origin: vl.menu(countries)});
// variables to get the dashboard to fit nicely
const scatter_sq = width * 0.47;
const hist_width = width * 0.36;
const num_hist = 4;
const brush = vl.selectInterval().encodings('x').resolve('intersect');
// base histogram
const hist = vl.markBar()
.encode(
vl.x().fieldQ(vl.repeat('row'))
.bin({maxbins: 100, minstep: 1}) // up to 100 bins, but no smaller than 1 unit
.axis({format: 'd', titleAnchor: 'start'}), // integer format, left-aligned title
vl.y().count().title(null));

// combined histogram with total in grey and selected in blue (when selected)
// and repeated for each of the attributes
const hist_layer = vl.layer(
hist.select(brush).encode(vl.color().value('lightgrey')), // turn all grey when selected
hist.transform(vl.filter(brush))) // layer selected values on top in default blue
.height((scatter_sq/num_hist)-(10*num_hist))
.width(hist_width)
.repeat({row: ['Cylinders', 'Displacement', 'Weight_in_lbs', 'Acceleration']});
// scatterplot
const scatter = vl.markPoint()
.select(selection)
.transform(vl.filter(selection))
.encode(
vl.x().fieldQ("Horsepower"),
vl.y().fieldQ("Miles_per_Gallon"),
vl.color().if(brush, vl.value('steelblue')).value('grey'),
vl.opacity().if(brush, vl.value(0.8)).value(0.1),
vl.tooltip(['Name', 'Origin', 'Year'].concat(quant_columns))
)
.height(scatter_sq).width(scatter_sq);
// place the histograms and scatterplot
return vl.hconcat(hist_layer, scatter)
.data(cars) // all use the same data, so it can be just specified here
.render();
}
Insert cell
Insert cell
Insert cell
Insert cell
data = formatData(cars)
Insert cell
Insert cell
Insert cell
hist_columns = {
let temp = []
quant_columns.forEach(d => {if (d != x && d != y) temp.push(d);})
return temp;
}
// there's probably a short more JavaScript-y way to do this...
Insert cell
Insert cell
import {kmeans} from "@spond/k-means-clustering-algorithm"
Insert cell
function formatData (local_data) {
let new_data = JSON.parse(JSON.stringify(local_data))
new_data.forEach(d => {d.x = d[x]; d.y = d[y];})
return new_data
}
Insert cell
import { vl } from "@vega/vega-lite-api"
Insert cell
import {uniqueValid} from '@uwdata/data-utilities'
Insert cell
import {Range, Select} from "@observablehq/inputs"
Insert cell
d3 = require("d3@6")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more